package com.xiannimei.web.controller;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;

import net.sf.json.JSONObject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.xiannimei.BusinessException;
import com.xiannimei.Constants;
import com.xiannimei.model.Member;
import com.xiannimei.model.Platform;
import com.xiannimei.model.command.LoginCmd;
import com.xiannimei.model.command.RegisterCmd;
import com.xiannimei.service.MemberService;
import com.xiannimei.service.oauth.OAuthManager;
import com.xiannimei.service.oauth.OAuthProfile;
import com.xiannimei.util.AuthUtil;
import com.xiannimei.util.Base64Util;
import com.xiannimei.util.CaptchaUtil;
import com.xiannimei.util.ZipUtil;
import com.xiannimei.util.validate.ValidateUtil;
import com.xiannimei.web.MemberProfile;

/**
 * AuthController 处理用户授权相关的控制器
 * 
 * @author xinyuan.guo
 * 
 * @createDate 2013-7-3 上午11:09:35
 */
@Controller
@RequestMapping("/auth")
public class AuthController {

	final static Logger log = LoggerFactory.getLogger(AuthController.class);

	@Autowired
	MemberService memberService;

	@Autowired
	OAuthManager oauthSina;
	@Autowired
	OAuthManager oauthTencent;

	static final int E_LOCALPARAMERROR = 600301;

	@RequestMapping(value = "/logout.htm", method = RequestMethod.GET)
	public String exitLogin(HttpSession httpSession) {
		httpSession.removeAttribute(Constants.SESSION_USER_CONTEXT);
		return "redirect:" + "/";
	}

	@RequestMapping("/register.htm")
	public String register(Model model) {
		ValidateUtil.getValidateJson(model, RegisterCmd.class);
		return "/auth/register";
	}

	@ResponseBody
	@RequestMapping(value = "/registering.json", method = RequestMethod.POST)
	public Object registering(Model model, @Valid RegisterCmd registerCmd, Errors errors, HttpSession session,
			HttpServletRequest req) {
		model.asMap().clear();
		if (!errors.hasErrors()) {
			if (CaptchaUtil.isVerifyCodeCoincide(session, registerCmd.getCaptcha())) {
				MemberProfile mp;

				Object opObj = session.getAttribute(Constants.SESSION_OP);
				if (opObj != null && opObj instanceof OAuthProfile) {
					mp = memberService.register((OAuthProfile) opObj, registerCmd);
					session.removeAttribute(Constants.SESSION_OP);
				} else
					mp = memberService.registerMember(registerCmd);
				AuthUtil.setUserDetails(session, mp);
				model.addAttribute("result", 0);
				model.addAttribute("lastUrl", getLastestUrl(req));
				model.addAttribute("msg", "登录成功，即将跳转");
			} else {
				errors.rejectValue("captcha", null);
				model.addAttribute("result", 2);
				model.addAttribute("errors", ValidateUtil.getErrorFileds(errors));
			}
		} else {
			model.addAttribute("result", 3);
			model.addAttribute("errors", ValidateUtil.getErrorFileds(errors));
		}
		return model;
	}

	@RequestMapping("/login.htm")
	public String login(Model model) {
		ValidateUtil.getValidateJson(model, RegisterCmd.class);
		return "/auth/login";
	}

	@ResponseBody
	@RequestMapping("/loging.json")
	public Object loging(Model model, @Valid LoginCmd loginCmd, Errors errors, HttpSession session, HttpServletRequest req) {
		model.asMap().clear();
		if (!errors.hasErrors()) {
			if (CaptchaUtil.isVerifyCodeCoincide(session, loginCmd.getCaptcha())) {
				MemberProfile mp = memberService.localLoginMember(loginCmd);
				if (mp != null) {
					AuthUtil.setUserDetails(session, mp);
					model.addAttribute("result", 0);
					model.addAttribute("lastUrl", getLastestUrl(req));
					model.addAttribute("msg", "登录成功，即将跳转");
				} else {
					model.addAttribute("result", 1);
					model.addAttribute("msg", "登录失败，登录名或密码错误");
				}
			} else {
				errors.rejectValue("captcha", null);
				model.addAttribute("result", 2);
				model.addAttribute("errors", ValidateUtil.getErrorFileds(errors));
			}
		} else {
			model.addAttribute("result", 3);
			model.addAttribute("errors", ValidateUtil.getErrorFileds(errors));
		}
		return model;
	}

	/**
	 * 准备跳转联合登录
	 * 
	 * @param type 第三方登录实现类型
	 * 
	 * @return 第三方登录连接
	 */
	@RequestMapping("/federatedLogin.htm")
	public String federatedLogin(@RequestParam int type) {
		return "redirect:" + getOAuthLoginManager(type).getLoginUrl(null);
	}

	/**
	 * 联合登录回调
	 * 
	 * @param req 用户登录存储session信息
	 * @param type 第三方登录实现类型
	 * @param code 第三方授权code
	 * @param state 回调参数
	 * @return 登录后跳转的页面连接
	 */
	@RequestMapping("/loginCallback.htm")
	public String loginCallback(@RequestParam int type, @RequestParam String code,
			@RequestParam(required = false) String state, HttpSession session, HttpServletRequest req) {
		OAuthProfile authProfile = getOAuthLoginManager(type).login(code);
		Member localMember = memberService.findThirdPartyUID(authProfile.getUid(), authProfile.getPlatformId());
		if (localMember == null) {
			session.setAttribute(Constants.SESSION_OP, authProfile);
			return "redirect:" + "/auth" + "/register.htm";
		} else {
			MemberProfile mp = new MemberProfile(localMember);
			doCallback(state, mp);
			AuthUtil.setUserDetails(session, mp);
			return "redirect:" + getLastestPath(session);
		}
	}

	/**
	 * 处理回调参数
	 */
	private void doCallback(String state, MemberProfile mp) {
		try {
			if (state != null) {
				JSONObject jo = decodeUrlParam2JsonObject(state);
				if (jo != null) {
					// 为以后需求准备
				}
			}
		} catch (IOException e) {
			log.warn("callback 'state' param decode error : " + state);
		}
	}

	/**
	 * 获取第三方登录实现类型
	 * 
	 * @param type 第三方登录实现类型
	 * @return 第三方登录实现
	 */
	private OAuthManager getOAuthLoginManager(int type) {
		switch (type) {
			case Platform.TYPE_SINA :
				return oauthSina;
			case Platform.TYPE_TENCENT :
				return oauthTencent;
			default:
				throw new BusinessException(E_LOCALPARAMERROR);
		}
	}

	/**
	 * 获取 最后访问的url,用于登录后的前台跳转
	 */
	private String getLastestUrl(HttpServletRequest req) {
		return AuthUtil.getServerRootWithContextPath(req) + getLastestPath(req.getSession());
	}

	/**
	 * 获取 最后访问的url,用于登录后的后台跳转
	 */
	private String getLastestPath(HttpSession session) {
		String lastViewUrl = (String) session.getAttribute(Constants.SESSION_LATEST_VIEW_URL);
		return lastViewUrl == null ? Constants.DEFAULT_LOGINED_URL : lastViewUrl;
	}

	public static String encodeJsonObject2UrlParam(JSONObject jo) throws IOException {
		return Base64Util.encode(ZipUtil.gzipString(jo.toString()));
	}

	public static JSONObject decodeUrlParam2JsonObject(String jo) throws IOException {
		return JSONObject.fromObject(ZipUtil.ungzipBytes(Base64Util.decode(jo)));
	}
}
